﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GLWrap.MathExt;
using Sharp3D.Math.Core;
using Tao.OpenGl;

namespace GLWrap.SceneObjects
{
    public class Light : SceneObject, IDisposable
    {
        private Vector3F _ambient;
        public Vector3F Ambient
        {
            get { return _ambient; }
            set
            {
                _ambient = value;
                _dirty = true;
            }
        }

        private Vector3F _diffuse;
        public Vector3F Diffuse
        {
            get { return _diffuse; }
            set
            {
                _diffuse = value;
                _dirty = true;
            }
        }

        private Vector3F _specular;
        public Vector3F Specular
        {
            get { return _specular; }
            set
            {
                _specular = value;
                _dirty = true;
            }
        }

        private Vector3F _position;
        public Vector3F Position
        {
            get { return _position; }
            set
            {
                _position = value;
                _dirty = true;
            }
        }

        public bool IsDirectional { get; set; }
        public Vector3F Direction { get; set; }
        public float CutOff { get; set; }

        private bool _dirty;
        private readonly int _lightId;
        private static int _globalLightCounter;
        private static readonly int[] Lights = {     
                                                       Gl.GL_LIGHT0, 
                                                       Gl.GL_LIGHT1, 
                                                       Gl.GL_LIGHT2, 
                                                       Gl.GL_LIGHT3, 
                                                       Gl.GL_LIGHT4, 
                                                       Gl.GL_LIGHT5, 
                                                       Gl.GL_LIGHT6, 
                                                       Gl.GL_LIGHT7, 
                                                };

        public Light()
        {
            _dirty = true;
            _lightId = Lights[_globalLightCounter++ % Lights.GetLength(0)];
            Gl.glEnable(_lightId);

            Position = new Vector3F(0,0,0);
            Ambient = new Vector3F(0,0,0);
            Diffuse = new Vector3F(1, 1, 1);
            Specular = new Vector3F(1,1,1);

        }

        public void ApplyLightParams()
        {
            //TODO: refactor
            Gl.glLightfv(_lightId, Gl.GL_AMBIENT, Ambient.GetArray().Concat(new float[] { 1 }).ToArray());
            Gl.glLightfv(_lightId, Gl.GL_DIFFUSE, Diffuse.GetArray().Concat(new float[] { 1 }).ToArray());
            Gl.glLightfv(_lightId, Gl.GL_SPECULAR, Specular.GetArray().Concat(new float[] { 1 }).ToArray());
            Gl.glLightfv(_lightId, Gl.GL_POSITION, Position.GetArray().Concat(new float[] { 1 }).ToArray());
        }

        public void Dispose()
        {
            Gl.glDisable(_lightId);
        }

        protected override void InternalDraw(GlSceneManager sceneManager)
        {
            if (_dirty)
            {
                ApplyLightParams();
                _dirty = false;
            }

        }
    }
}
